// ***********************************************************************
// Assembly         : GeYiHome.Domain
// Author           : wzx
// Created          : 03-29-2017
//
// Last Modified By : wzx
// Last Modified On : 03-29-2017
// ***********************************************************************
// <copyright file="Repository.cs" company="Nl">
//     Copyright ©  2017
// </copyright>
// <summary></summary>
// ***********************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using GeYiHome.Db.DbContent;
using GeYiHome.Db.IDbBase;
using GeYiHome.Domain.Entities;
using GeYiHome.Domain.Specification.SpecAbstract;
using GeYiHome.PublicLibrary;
using EcgCloudDbContext = GeYiHome.Db.DbContent.EcgCloudDbContext;

namespace GeYiHome.Db.DbBase
{
    /// <summary>
    /// Class BaseBal.
    /// </summary>
    /// <typeparam name="TEntity">The type of the t entity.</typeparam>
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity, new()
    {
        private readonly IUnitOfWork _unitOfWork;

        public Repository()
        {
            _unitOfWork = EcgContentFactory.GetCurrentDbContext();
        }

        public IUnitOfWork UnitOfWork => _unitOfWork;

        public TEntity Get<TKey>(TKey id)
        {
            var entities = this.GetAll();
            return entities.FirstOrDefault(x => x.Id.ToString().Equals(id.ToString()));
        }

        public IQueryable<TEntity> GetAll()
        {
            return _unitOfWork.GetAll<TEntity>();
        }

        public IQueryable<TEntity> GetAllMatching(ISpecification<TEntity> specification)
        {
            return GetAll().Where(specification.SatisfiedBy());
        }

        public DataPageList<TEntity> GetPageList<TK>(int pageIndex, int pageSize, ISpecification<TEntity> specification,
            Expression<Func<TEntity, TK>> orderByExpression,
            SortEnum sortOrder)
        {
            return this.GetPageList(this.GetAll(), pageIndex, pageSize, specification,
                orderByExpression, sortOrder);
        }

        public DataPageList<TEntity> GetPageList<TK>(IQueryable<TEntity> entities, int pageIndex, int pageSize,
            ISpecification<TEntity> specification,
            Expression<Func<TEntity, TK>> orderByExpression, SortEnum sortOrder)
        {
            var efContext = entities;
            var skip = pageSize * (pageIndex - 1);
            var take = pageSize;
            var totalCount = 0;

            if (skip == 0)
            {
                totalCount = efContext.Count(specification.SatisfiedBy());
            }

            switch (sortOrder)
            {
                case SortEnum.Asc:
                    var pagedGroupAscending =
                        efContext.Where(specification.SatisfiedBy())
                            .OrderBy(orderByExpression)
                            .Skip(skip)
                            .Take(take);

                    return new DataPageList<TEntity>()
                    {
                        PageSize = pageSize,
                        Page = pageIndex,
                        Records = totalCount,
                        Rows = pagedGroupAscending.ToList()
                    };

                case SortEnum.Desc:
                    var pagedGroupDescending =
                        efContext
                            .Where(specification.SatisfiedBy())
                            .OrderByDescending(orderByExpression)
                            .Skip(skip)
                            .Take(take);
                    return new DataPageList<TEntity>()
                    {
                        PageSize = pageSize,
                        Page = pageIndex,
                        Records = totalCount,
                        Rows = pagedGroupDescending.ToList()
                    };
                case SortEnum.Original:
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(sortOrder), sortOrder, null);
            }
            return null;
        }

        public void Modify(TEntity entity)
        {
            _unitOfWork.Modify(entity);
        }

        public void Modify(IEnumerable<TEntity> entities)
        {
            entities.ForEach(Modify);
        }

        public void Modify(ISpecification<TEntity> specification, Expression<Func<TEntity, TEntity>> value)
        {
            _unitOfWork.Modify(specification, value);
        }

        public void Remove(TEntity entity)
        {
            _unitOfWork.Remove(entity);
        }

        public void Remove(ISpecification<TEntity> specification)
        {
            _unitOfWork.Remove(specification);
        }

        public void Remove(IEnumerable<TEntity> entities)
        {
            entities.ForEach(Remove);
        }

        public void Remove<TKey>(TKey id)
        {
            _unitOfWork.Remove<TEntity, TKey>(id);
        }

        public void Add(IEnumerable<TEntity> entities)
        {
            entities.ForEach(Add);
        }

        public void Add(TEntity entity)
        {
            _unitOfWork.Add(entity);
        }

        /// <summary>
        /// 执行返回查询语句
        /// </summary>
        /// <typeparam name="TEntity">The type of the t entity.</typeparam>
        /// <param name="sqlQuery">The SQL query.</param>
        /// <param name="parameters">The parameters.</param>
        /// <returns>IEnumerable&lt;TEntity&gt;.</returns>
        public IEnumerable<TEntity> ExecuteQuery(string sqlQuery, params object[] parameters)
        {
            return _unitOfWork.ExecuteQuery<TEntity>(sqlQuery, parameters);
        }

        /// <summary>
        /// 执行sql语句
        /// </summary>
        /// <param name="sqlCommand"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int ExecuteCommand(string sqlCommand, params object[] parameters)
        {
            return _unitOfWork.ExecuteCommand(sqlCommand, parameters);
        }

    }
}
